package model

import (
	"context"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gtime"
	v1 "goAdminV1/api/permissions/v1"
	"goAdminV1/internal/dao"
	"goAdminV1/internal/middleware"
	"goAdminV1/internal/model/entity"
	"goAdminV1/utility"
	"sort"
	"strconv"
	"time"
)

// Departments 部门模型
type Departments struct{}

// PermissionResult 定义权限查询结果的结构体
type PermissionResult struct {
	Data  []*v1.Permission `json:"data"`
	Total int              `json:"total"`
}

// GetPermissionList 获取权限列表
func GetPermissionList(ctx context.Context, req *v1.PermissionListReq) (*PermissionResult, error) {
	offset := (req.Page - 1) * req.Limit

	// 构建基础查询
	query := dao.CaPermissions.Ctx(ctx).Where("deleted_at", 0)

	// 添加查询条件
	if req.Username != "" {
		query = query.Where("username", req.Username)
	}
	if req.Email != "" {
		query = query.Where("email", req.Email)
	}
	if req.Status > 0 {
		query = query.Where("status", req.Status)
	}
	if req.DepartmentId > 0 {
		query = query.Where("department_id", req.DepartmentId)
	}

	// 复制查询用于统计总数
	countQuery := query.Clone()
	var total int64
	_, err := countQuery.Count(&total)
	if err != nil {
		return nil, err
	}

	// 查询根节点（parent_id = 0）
	rootQuery := query.Where("parent_id", 0).Order("created_at DESC").Limit(req.Limit).Offset(offset)
	var rootNodes []*v1.Permission
	err = rootQuery.Scan(&rootNodes)
	if err != nil {
		return nil, err
	}

	// 转换根节点的时间格式
	convertPermissionTimeFormat(rootNodes)

	// 根据 From 参数决定递归查询方式
	for _, rootNode := range rootNodes {
		if req.From == "role" {
			// 角色查询模式，不使用 actions 字段
			rootNode.Actions = []*v1.Permission{}
			queryChildrenForRole(ctx, rootNode)
		} else {
			// 默认查询模式
			rootNode.Actions = []*v1.Permission{}
			queryChildren(ctx, rootNode)
		}
	}

	// 对根节点和每个节点的子节点进行排序
	sortPermissions(rootNodes)

	result := &PermissionResult{
		Data:  rootNodes,
		Total: int(total),
	}
	return result, nil
}

// queryChildren 递归查询子节点（默认模式）
func queryChildren(ctx context.Context, parent *v1.Permission) {
	query := dao.CaPermissions.Ctx(ctx).Where("parent_id", parent.Id).Where("deleted_at", 0).Order("created_at DESC")
	var children []*v1.Permission
	err := query.Scan(&children)
	if err != nil {
		g.Log().Error(ctx, err)
		return
	}

	// 转换子节点的时间格式
	convertPermissionTimeFormat(children)

	parent.Children = children
	for _, child := range children {
		if parent.ParentId == 0 {
			// 第二层子节点查询 actions
			child.Children = []*v1.Permission{}
			queryActions(ctx, child)
		} else {
			// 其他层级继续递归查询 children
			queryChildren(ctx, child)
		}
	}
}

// queryChildrenForRole 递归查询子节点（角色模式）
func queryChildrenForRole(ctx context.Context, parent *v1.Permission) {
	query := dao.CaPermissions.Ctx(ctx).Where("parent_id", parent.Id).Where("deleted_at", 0).Order("created_at DESC")
	var children []*v1.Permission
	err := query.Scan(&children)
	if err != nil {
		g.Log().Error(ctx, err)
		return
	}

	// 转换子节点的时间格式
	convertPermissionTimeFormat(children)

	parent.Children = children
	for _, child := range children {
		// 角色模式下，所有子节点都放在 Children 中
		queryChildrenForRole(ctx, child)
	}
}

// queryActions 查询 actions
func queryActions(ctx context.Context, parent *v1.Permission) {
	query := dao.CaPermissions.Ctx(ctx).Where("parent_id", parent.Id).Where("deleted_at", 0)
	var actions []*v1.Permission
	err := query.Scan(&actions)
	if err != nil {
		g.Log().Error(ctx, err)
		return
	}

	// 转换actions的时间格式
	convertPermissionTimeFormat(actions)

	parent.Actions = actions
}

// convertPermissionTimeFormat 转换权限记录的时间格式
func convertPermissionTimeFormat(permissions []*v1.Permission) {
	for _, p := range permissions {
		if p.CreatedAt != "" {
			if t, err := gtime.StrToTime(p.CreatedAt); err == nil {
				p.CreatedAt = t.Format("Y-m-d H:i")
			}
		}
		if p.UpdatedAt != "" {
			if t, err := gtime.StrToTime(p.UpdatedAt); err == nil {
				p.UpdatedAt = t.Format("Y-m-d H:i")
			}
		}
	}
}

// sortPermissions 对权限列表进行排序
func sortPermissions(permissions []*v1.Permission) {
	sort.Slice(permissions, func(i, j int) bool {
		return permissions[i].Sort < permissions[j].Sort
	})
	for _, p := range permissions {
		sortPermissions(p.Children)
	}
}

// GetPermissionDetailById 通过 ID 获取权限详情
func GetPermissionDetailById(ctx context.Context, id int) (*v1.PermissionDetailRes, error) {
	var permission v1.PermissionDetailRes
	err := dao.CaPermissions.Ctx(ctx).Where("id", id).Scan(&permission)
	if err != nil {
		return nil, gerror.Wrapf(err, "获取权限详情失败: %v", err)
	}
	if permission.Id == 0 {
		return nil, gerror.New("未找到该权限信息")
	}
	return &permission, nil
}

// PermissionsAdd 添加权限（菜单或action）
func PermissionsAdd(ctx context.Context, req *v1.PermissionCreateReq) error {
	now := time.Now().Unix()
	permission := &entity.CaPermissions{
		Sort:           req.Sort,
		Keepalive:      req.Keepalive,
		Type:           req.Type,
		Hidden:         req.Hidden,
		PermissionName: req.PermissionName,
		Module:         req.Module,
		Route:          req.Route,
		Redirect:       req.Redirect,
		ParentId:       req.ParentId,
		Icon:           req.Icon,
		Component:      req.Component,
		CreatedAt:      uint(now),
		UpdatedAt:      uint(now),
	}

	_, err := dao.CaPermissions.Ctx(ctx).Data(permission).Insert()
	if err != nil {
		return err
	}

	return nil
}

// PermissionsUpdate 更新权限
func PermissionsUpdate(ctx context.Context, req *v1.PermissionUpdateReq) error {
	// 如果请求中的Redirect为nil，转换为空字符串
	var redirectStr string
	if redirect, ok := req.Redirect.(string); ok {
		redirectStr = redirect
	} else if req.Redirect == nil {
		redirectStr = ""
	} else {
		// 处理其他可能的类型情况，这里简单返回错误
		return gerror.New("Redirect字段类型错误")
	}

	createdAtUnix := utility.DateToTime(req.CreatedAt, "")
	updatedAtUnix := utility.DateToTime(req.UpdatedAt, "")

	permission := &entity.CaPermissions{
		Id:             uint(req.Id),
		Type:           req.Type,
		ParentId:       req.ParentId,
		PermissionName: req.PermissionName,
		PermissionMark: req.PermissionMark,
		Icon:           req.Icon,
		Module:         req.Module,
		Route:          req.Route,
		Component:      req.Component,
		Redirect:       redirectStr,
		Keepalive:      req.Keepalive,
		Hidden:         req.Hidden,
		Sort:           req.Sort,
		ActiveMenu:     req.ActiveMenu,
		CreatorId:      uint(req.CreatorId),
		CreatedAt:      uint(createdAtUnix),
		UpdatedAt:      uint(updatedAtUnix),
	}

	_, err := dao.CaPermissions.Ctx(ctx).Where("id", req.Id).Data(permission).Update()
	if err != nil {
		return gerror.Wrapf(err, "更新权限数据失败: %v", err)
	}

	return nil
}

// PermissionsDelete 删除权限
func PermissionsDelete(ctx context.Context, id int) error {
	// 获取当前时间戳
	now := time.Now().Unix()
	update := map[string]interface{}{
		"deleted_at": now,
	}
	_, err := dao.CaPermissions.Ctx(ctx).Where("id", id).Data(update).Update()
	if err != nil {
		return gerror.Wrapf(err, "删除权限数据失败: %v", err)
	}
	return nil
}

// DepartmentsResult 定义部门查询结果的结构体
type DepartmentsResult struct {
	Data  []*v1.DepartmentListItem `json:"data"`
	Total int                      `json:"total"`
}

// DepartmentsGetList 获取部门列表
func DepartmentsGetList(ctx context.Context, req *v1.DepartmentListReq) (*DepartmentsResult, error) {
	var items []*v1.DepartmentListItem

	// 构建基础查询
	query := dao.CaDepartments.Ctx(ctx)

	// 添加查询条件
	if req.DepartmentName != "" {
		query = query.Where("department_name LIKE?", "%"+req.DepartmentName+"%")
	}

	// 复制查询用于统计总数
	countQuery := *query
	var total int
	_, err := countQuery.Count(&total)
	if err != nil {
		return nil, err
	}

	// 应用分页并查询部门列表
	err = query.Scan(&items)
	if err != nil {
		return nil, err
	}

	// 处理子部门数据
	for _, item := range items {
		children, err := getChildren(ctx, item.Id)
		if err != nil {
			return nil, err
		}
		item.Children = children
	}

	return &DepartmentsResult{
		Data:  items,
		Total: total,
	}, nil
}

// getChildren 获取子部门列表
func getChildren(ctx context.Context, parentId int) ([]*v1.DepartmentListItem, error) {
	var children []*v1.DepartmentListItem
	err := dao.CaDepartments.Ctx(ctx).Where("parent_id", parentId).Scan(&children)
	if err != nil {
		return nil, err
	}
	for _, child := range children {
		grandChildren, err := getChildren(ctx, child.Id)
		if err != nil {
			return nil, err
		}
		child.Children = grandChildren
	}
	return children, nil
}

func DepartmentsCreate(ctx context.Context, req *v1.DepartmentCreateReq) error {
	parentId, _ := strconv.Atoi(req.ParentId)
	department := &entity.CaDepartments{
		ParentId:       parentId,
		DepartmentName: req.DepartmentName,
		Principal:      req.Principal,
		Email:          req.Email,
		Mobile:         req.Mobile,
		Sort:           req.Sort,
	}

	_, err := dao.CaDepartments.Ctx(ctx).Data(department).Insert()
	if err != nil {
		return gerror.Wrapf(err, "插入部门数据失败: %v", err)
	}
	return nil
}

// DepartmentsUpdate 更新部门信息
func DepartmentsUpdate(ctx context.Context, req *v1.DepartmentUpdateReq) error {
	parentId, _ := strconv.Atoi(req.ParentId)
	department := &entity.CaDepartments{
		Id:             uint(req.Id),
		ParentId:       parentId,
		DepartmentName: req.DepartmentName,
		Principal:      req.Principal,
		Email:          req.Email,
		Mobile:         req.Mobile,
		Sort:           req.Sort,
	}
	_, err := dao.CaDepartments.Ctx(ctx).Where("id", req.Id).Data(department).Update()
	if err != nil {
		return gerror.Wrapf(err, "更新部门数据失败: %v", err)
	}
	return nil
}

// DepartmentsDelete 删除部门
func DepartmentsDelete(ctx context.Context, id int) error {
	now := time.Now().Unix()
	update := map[string]interface{}{
		"deleted_at": now,
	}
	_, err := dao.CaPermissions.Ctx(ctx).Where("id", id).Data(update).Update()
	if err != nil {
		return gerror.Wrapf(err, "删除权限数据失败: %v", err)
	}
	return nil
}

// JobListResult 定义岗位查询结果的结构体
type JobListResult struct {
	Data  []*v1.JobListItem `json:"data"`
	Total int               `json:"total"`
}

// GetJobList 获取岗位列表
func GetJobList(ctx context.Context, req *v1.JobListReq) (*JobListResult, error) {
	var items []*v1.JobListItem
	var total int

	offset := (req.Page - 1) * req.Limit

	// 构建基础查询
	query := dao.CaJobs.Ctx(ctx)

	// 添加查询条件
	if req.JobName != "" {
		query = query.Where("job_name LIKE?", "%"+req.JobName+"%")
	}

	// 复制查询用于统计总数
	countQuery := *query
	_, err := countQuery.Count(&total)
	if err != nil {
		return nil, err
	}

	// 应用分页并查询岗位列表
	err = query.Limit(req.Limit).Offset(offset).Order("sort desc").Scan(&items)
	if err != nil {
		return nil, err
	}
	// 遍历 items 并转换时间戳
	for _, item := range items {
		item.CreatedAt = strconv.FormatInt(utility.DateToTime(item.CreatedAt, ""), 10)
		item.UpdatedAt = strconv.FormatInt(utility.DateToTime(item.UpdatedAt, ""), 10)
	}
	return &JobListResult{
		Data:  items,
		Total: total,
	}, nil
}

// CreateJob 创建岗位
func CreateJob(ctx context.Context, req *v1.JobCreateReq) error {
	now := time.Now().Unix()

	// 获取用户ID
	userIDValue := ctx.Value(middleware.ContextUserIDKey)
	userID, ok := userIDValue.(uint)
	if !ok {
		return gerror.New("从上下文中获取的用户 ID 类型错误")
	}

	job := &entity.CaJobs{
		JobName:     req.JobName,
		Coding:      req.Coding,
		Description: req.Description,
		Sort:        req.Sort,
		Status:      req.Status,
		CreatedAt:   uint(now),
		UpdatedAt:   uint(now),
		CreatorId:   userID,
	}

	_, err := dao.CaJobs.Ctx(ctx).Data(job).Insert()
	if err != nil {
		return gerror.Wrapf(err, "插入岗位数据失败: %v", err)
	}
	return nil
}

// JobWithCreator 包含岗位信息和创建者信息的结构体
type JobWithCreator struct {
	entity.CaJobs
	Creator string `json:"creator"`
}

// GetJobById 根据岗位 ID 获取岗位信息
func GetJobById(ctx context.Context, id int) (*JobWithCreator, error) {
	var job entity.CaJobs
	err := dao.CaJobs.Ctx(ctx).Where("id", id).Scan(&job)
	if err != nil {
		return nil, gerror.Wrap(err, "查询岗位信息时数据库操作出错")
	}
	if job.Id == 0 {
		return nil, gerror.Wrap(err, "ID错误")
	}
	var creator string
	creator, err = GetCreatorByID(ctx, int(job.CreatorId))
	if err != nil {
		return nil, err
	}
	result := &JobWithCreator{
		CaJobs:  job,
		Creator: creator,
	}
	return result, nil
}

// UpdateJobStatus 更新岗位状态
func UpdateJobStatus(ctx context.Context, data g.Map) error {
	id, ok := data["id"].(int)
	if !ok {
		return gerror.New("更新数据中 ID 类型错误")
	}
	status, ok := data["status"].(int)
	if !ok {
		return gerror.New("更新数据中 status 类型错误")
	}
	_, err := dao.CaJobs.Ctx(ctx).Where("id", id).Data(g.Map{
		"status": status,
	}).Update()
	if err != nil {
		return gerror.Wrap(err, "更新岗位状态时数据库操作出错")
	}
	return nil
}

// UpdateJob 修改岗位
func UpdateJob(ctx context.Context, req *v1.JobUpdateReq) error {
	now := time.Now().Unix()
	job := &entity.CaJobs{
		Id:          uint(req.Id),
		JobName:     req.JobName,
		Coding:      req.Coding,
		Description: req.Description,
		Sort:        req.Sort,
		Status:      req.Status,
		UpdatedAt:   uint(now),
	}
	_, err := dao.CaJobs.Ctx(ctx).Where("id", req.Id).Data(job).Update()
	if err != nil {
		return gerror.Wrapf(err, "更新岗位数据失败: %v", err)
	}
	return nil
}

// JobDelete 删除岗位
func JobDelete(ctx context.Context, id int) error {
	now := time.Now().Unix()
	update := map[string]interface{}{
		"deleted_at": now,
	}
	_, err := dao.CaJobs.Ctx(ctx).Where("id", id).Data(update).Update()
	if err != nil {
		return gerror.Wrapf(err, "删除岗位数据失败: %v", err)
	}
	return nil
}
